package kuzmenkov.oip.controller.applet;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Stroke;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.Path2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.RenderedImage;
import java.util.List;
import java.util.logging.Logger;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

/**
 * Class renders a selected image
 * 
 * @author Michael Kuzmenkov
 * 
 */
public class RenderedImagePanel extends JPanel {
	/**
	 * 
	 */
	private static final long serialVersionUID = 97418773778905814L;

	private Logger log = Logger.getLogger(RenderedImagePanel.class.getName());

	/**
	 * An image which is rendered
	 */
	private RenderedImage image = null;
	/**
	 * It describes an image transformation before the image is rendered
	 */
	AffineTransform xform = new AffineTransform();

	/**
	 * A panel which renders a nonscaled image
	 */
	private RendPanel2 panel2;
	

	private Point2D leftTopCorner;
	private Point2D rightBottomCorner;
	private Rectangle2D areaSelection = new Rectangle2D.Double();
	private Rectangle2D firstPoint = new Rectangle2D.Double();
	private BasicStroke selectStroke = new BasicStroke(1f,
			BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
	private Color selectColor = new Color(0, 255, 0);
	private ISelectableUIC selectionListener;
	
	/**
	 * The list of the polygons for displaying 
	 */
	private List polygons;

	public RenderedImagePanel(String paramName) {
		addOriginalViewer(paramName);

	}

	private void addOriginalViewer(String paramName) {
		I18nTool itool = I18nTool.getInstance();
		JFrame viewer = new JFrame(paramName+" - "+itool.getMessage("imageFrameTitle"));
		viewer.setSize(new Dimension(640, 480));
		viewer.setLocationRelativeTo(null);
		panel2 = new RendPanel2();
		viewer.getContentPane().add(new JScrollPane(panel2));
		MouseListener list = new ShowFrameByDblClick(viewer);
		addMouseListener(list);
		panel2.addMouseListener(list);
		panel2.addMouseListener(new AreaSelectionL());
	}

	private class ShowFrameByDblClick extends MouseAdapter {
		private JFrame frame = null;

		public ShowFrameByDblClick(JFrame frame) {
			if (frame == null)
				log.severe("frame is null");
			this.frame = frame;
		}

		public void mouseClicked(MouseEvent e) {
			if (e.getClickCount() == 2) {
				frame.setVisible(!frame.isVisible());
			}

		}
	}

	private class RendPanel2 extends JPanel {

		/**
		 * 
		 */
		private static final long serialVersionUID = 6322393630624649291L;
		private RenderedImage image = null;
		private AffineTransform xform = new AffineTransform();

		public void setImage(RenderedImage image) {
			this.image = image;
			if (image != null)
				setPreferredSize(new Dimension(image.getWidth(), image
						.getHeight()));
			updateUI();
		}

		protected void paintComponent(Graphics g) {
			super.paintComponent(g);
			Graphics2D g2d = (Graphics2D) g;
			log.info("entry");
			if (image != null) {
				Color oldc = g2d.getColor();
				g2d.setColor(selectColor);
				Stroke oldstr = g2d.getStroke();
				g2d.setStroke(selectStroke);

				g2d.drawRenderedImage(image, xform);

				if (leftTopCorner != null) {
					double centerX = leftTopCorner.getX();
					double centerY = leftTopCorner.getY();
					double cornerX = centerX + 1;
					double cornerY = centerY + 1;
					firstPoint.setFrameFromCenter(centerX, centerY, cornerX,
							cornerY);
					g2d.draw(firstPoint);
				}

				if (leftTopCorner != null && rightBottomCorner != null) {
					areaSelection.setFrameFromDiagonal(leftTopCorner,
							rightBottomCorner);
					g2d.draw(areaSelection);
				}
				
				if (polygons!=null && !polygons.isEmpty()){
					for (int i=0; i<polygons.size();i++){
						Path2D path = (Path2D) polygons.get(i);
						g2d.draw(path);
					}
					
					
				}

				g2d.setColor(oldc);
				g2d.setStroke(oldstr);

			}

		}
	}

	/**
	 * Sets the image which will be rendered
	 * 
	 * @param image
	 */
	public void setImage(RenderedImage image) {
		this.image = image;
		imageUpdate();
		panel2.setImage(image);
		repaint();
	}

	protected void paintComponent(Graphics g) {
		super.paintComponent(g);
		Graphics2D g2d = (Graphics2D) g;

		if (image != null) {
			g2d.drawRenderedImage(image, xform);

		}

	}

	public void imageUpdate() {
		if (image == null)
			return;

		
		
		int imgWidth = image.getWidth();
		int imgHeight = image.getHeight();
		int panelWidth = getWidth();
		int panelHeight = getHeight();

		log
				.info("imgHeight=" + imgHeight + ", imgWidth=" + imgWidth
						+ ", panelHeight=" + panelHeight + ", panelWidth="
						+ panelWidth);

		double s = 1;

		double tx = 0;
		double ty = 0;
		if (imgWidth > panelWidth && imgHeight <= panelHeight) {
			s = (double) panelWidth / (double) imgWidth;
		} else if (imgHeight > panelHeight && imgWidth <= panelWidth) {
			s = (double) panelHeight / (double) imgHeight;
		} else if (imgWidth > panelWidth && imgHeight > panelHeight) {
			if (imgWidth > imgHeight)
				s = (double) panelWidth / (double) imgWidth;
			else
				s = (double) panelHeight / (double) imgHeight;
		}
		tx = (panelWidth - (double) imgWidth * s) / 2.;
		ty = (panelHeight - (double) imgHeight * s) / 2.;
		log.info("s=" + s + ", tx=" + tx + ", ty=" + ty);
		xform = new AffineTransform(s, 0, 0, s, tx, ty);

	}

	private class AreaSelectionL extends MouseAdapter {

		public void mousePressed(MouseEvent e) {
			if (selectionListener != null) {
				log.info("entry");
				leftTopCorner = e.getPoint();
				rightBottomCorner = null;
				selectionListener.setSelection(null);
				panel2.repaint();
			}
		}

		public void mouseReleased(MouseEvent e) {
			if (selectionListener == null) {
				return;
			}

			rightBottomCorner = e.getPoint();
			
			if (leftTopCorner.equals(rightBottomCorner)){
				selectionListener.setSelection(null);
			}
			
			if (leftTopCorner != null && rightBottomCorner != null
					&& image != null) {
				log.info("entry");
				double x1 = leftTopCorner.getX();
				double y1 = leftTopCorner.getY();
				double x2 = rightBottomCorner.getX();
				double y2 = rightBottomCorner.getY();

				if (x1>x2){
					double t = x1;
					x1 = x2;
					x2 = t;
				}
				if (y1>y2){
					double t = y1;
					y1 = y2;
					y2 = t;
				}
					
				if (x2 > image.getWidth()){
					x2 = image.getWidth();
					rightBottomCorner.setLocation(x2, y2);
				}
				if (y2 > image.getHeight()){
					y2 = image.getHeight();
					rightBottomCorner.setLocation(x2, y2);
				}
				
				leftTopCorner.setLocation(x1,y1);
				rightBottomCorner.setLocation(x2, y2);
				
				Rectangle2D selection = new Rectangle2D.Float();
				selection.setFrameFromDiagonal(x1, y1, x2, y2);
				selectionListener.setSelection(selection);
				panel2.repaint();
			}
		}
	}

	public void setSelectionListener(ISelectableUIC selectionListener) {
		this.selectionListener = selectionListener;
		leftTopCorner = null;
		rightBottomCorner = null;
	}

	public void setPolygons(List polygons) {
		this.polygons = polygons;
		panel2.repaint();
		
	}

}
